package com.zzyl.nursing.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzyl.common.utils.CodeGenerator;
import com.zzyl.common.utils.IDCardUtils;
import com.zzyl.nursing.domain.*;
import com.zzyl.nursing.dto.CheckInApplyDto;
import com.zzyl.nursing.dto.CheckInConfigDto;
import com.zzyl.nursing.mapper.*;
import com.zzyl.nursing.service.ICheckInService;
import com.zzyl.nursing.vo.CheckInConfigVo;
import com.zzyl.nursing.vo.CheckInDetailVo;
import com.zzyl.nursing.vo.CheckInElderVo;
import com.zzyl.nursing.vo.ElderFamilyVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

/**
 * 入住Service业务层处理
 *
 * @author shilinfeng
 * @date 2024-11-04
 */
@Service
public class CheckInServiceImpl extends ServiceImpl<CheckInMapper, CheckIn> implements ICheckInService {
    @Autowired
    private CheckInMapper checkInMapper;

    @Autowired
    private ElderMapper elderMapper;

    @Autowired
    private BedMapper bedMapper;

    @Autowired
    private ContractMapper contractMapper;

    @Autowired
    private CheckInConfigMapper checkInConfigMapper;

    /**
     * 查询入住
     *
     * @param id 入住主键
     * @return 入住
     */
    @Override
    public CheckIn selectCheckInById(Long id) {
        return getById(id);
    }

    /**
     * 查询入住列表
     *
     * @param checkIn 入住
     * @return 入住
     */
    @Override
    public List<CheckIn> selectCheckInList(CheckIn checkIn) {
        return checkInMapper.selectCheckInList(checkIn);
    }

    /**
     * 新增入住
     *
     * @param checkIn 入住
     * @return 结果
     */
    @Override
    public int insertCheckIn(CheckIn checkIn) {
        return save(checkIn) ? 1 : 0;
    }

    /**
     * 修改入住
     *
     * @param checkIn 入住
     * @return 结果
     */
    @Override
    public int updateCheckIn(CheckIn checkIn) {
        return updateById(checkIn) ? 1 : 0;
    }

    /**
     * 批量删除入住
     *
     * @param ids 需要删除的入住主键
     * @return 结果
     */
    @Override
    public int deleteCheckInByIds(Long[] ids) {
        return removeByIds(Arrays.asList(ids)) ? 1 : 0;
    }

    /**
     * 删除入住信息
     *
     * @param id 入住主键
     * @return 结果
     */
    @Override
    public int deleteCheckInById(Long id) {
        return removeById(id) ? 1 : 0;
    }


    /**
     * 新增入住申请
     *
     * @param checkInApplyDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertCheckInApply(CheckInApplyDto checkInApplyDto) {
//        先查询老人对象 看是否有这个老人是否已经入住了
        LambdaQueryWrapper<Elder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Elder::getIdCardNo, checkInApplyDto.getCheckInElderDto().getIdCardNo())
                .eq(Elder::getStatus, 1);
        Elder elder = elderMapper.selectOne(wrapper);

//        1.校验老人是否已经入住
        if (!ObjectUtils.isEmpty(elder)) {
            throw new RuntimeException("该老人已经入住");
        }
//        2.更新床位状态为已入住
        Bed bed = bedMapper.selectBedById(checkInApplyDto.getCheckInConfigDto().getBedId());
        bed.setBedStatus(1);
        bedMapper.updateById(bed);
//        3.新增或更新老人表
        elder = insertOrUpdateElder(checkInApplyDto, bed);
//        4.新增签约办理
        insertContract(checkInApplyDto, elder);
//        5.新增入住信息
        CheckIn checkIn = insetCheckIn(checkInApplyDto, elder);
//        6.新增入住配置
        insertCheckInConfig(checkInApplyDto.getCheckInConfigDto(), checkIn);
    }


    /**
     * 新增入住配置
     *
     * @param checkInConfigDto
     * @param checkIn
     */
    private void insertCheckInConfig(CheckInConfigDto checkInConfigDto, CheckIn checkIn) {
        //        先从checkInApplyDto中把checkInConfig表抽取出来
        CheckInConfig checkInConfig = new CheckInConfig();
        BeanUtils.copyProperties(checkInConfigDto, checkInConfig);

        //        补全字段
        checkInConfig.setCheckInId(checkIn.getId());

        //        新增
        checkInConfigMapper.insert(checkInConfig);
    }

    /**
     * 新增入住信息
     *
     * @param checkInApplyDto
     * @param elder
     */
    private CheckIn insetCheckIn(CheckInApplyDto checkInApplyDto, Elder elder) {
        //        先从checkInApplyDto中把checkIn表抽取出来
        CheckIn checkIn = new CheckIn();
        BeanUtils.copyProperties(checkInApplyDto.getCheckInConfigDto(), checkIn);

//        补全字段
        checkIn.setElderId(elder.getId());
        checkIn.setElderName(elder.getName());
        checkIn.setIdCardNo(elder.getIdCardNo());
        checkIn.setBedNumber(elder.getBedNumber());
        checkIn.setStatus(0);
        checkIn.setRemark(JSONUtil.toJsonStr(checkInApplyDto.getElderFamilyDtoList()));
//        新增
        checkInMapper.insert(checkIn);
        return checkIn;
    }

    /**
     * 新增签约办理
     *
     * @param checkInApplyDto
     * @param elder
     */
    private void insertContract(CheckInApplyDto checkInApplyDto, Elder elder) {
//        先从checkInApplyDto中把contract表抽取出来
        Contract contract = new Contract();
        BeanUtils.copyProperties(checkInApplyDto.getCheckInContractDto(), contract);
//      补全字段
//        设置老人id
        contract.setElderId(Integer.parseInt(elder.getId().toString()));
//        合同编号
        contract.setContractNumber(CodeGenerator.generateContractNumber());
//        老人姓名
        contract.setElderName(elder.getName());
//        获取老人 入住/离住日期 判断当前合同的状态
        LocalDateTime startDate = checkInApplyDto.getCheckInConfigDto().getStartDate();
        LocalDateTime endDate = checkInApplyDto.getCheckInConfigDto().getEndDate();
        if (startDate.isBefore(LocalDateTime.now())) {
//            入住时间小于当前时间，则合同状态为已签合同 1已签约
            contract.setStatus(1);
        } else {
//            入住时间大于当前时间，则合同状态为未签合同 0未签约
            contract.setStatus(0);
        }
//        老人入住日期
        contract.setStartDate(startDate);
//        老人离住日期
        contract.setEndDate(endDate);

//        新增
        contractMapper.insert(contract);

    }

    /**
     * 新增或修改老人表
     *
     * @param checkInApplyDto
     * @param bed
     * @return elder 老人对象
     */
    private Elder insertOrUpdateElder(CheckInApplyDto checkInApplyDto, Bed bed) {
        LambdaQueryWrapper<Elder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Elder::getIdCardNo, checkInApplyDto.getCheckInElderDto().getIdCardNo())
                .ne(Elder::getStatus, 1);
        Elder elder = elderMapper.selectOne(wrapper);
//       根据elder的值 判断是否新增还是更新操作
        if (ObjectUtils.isEmpty(elder)) {
//        说明老人第一次入住 新增操作
            elder = new Elder();
            BeanUtils.copyProperties(checkInApplyDto.getCheckInElderDto(), elder);
            elder.setStatus(1);
            elder.setBedId(bed.getId());
            elder.setBedNumber(bed.getBedNumber());
            elderMapper.insert(elder);
        } else {
//            说明老人不是第一次入住 更新操作
            elder = new Elder();
            BeanUtils.copyProperties(checkInApplyDto.getCheckInElderDto(), elder);
            elder.setStatus(1);
            elder.setBedId(bed.getId());
            elder.setBedNumber(bed.getBedNumber());
            elderMapper.updateById(elder);
        }
        return elder;
    }


    /**
     * 获取入住详情信息
     *
     * @param id
     * @return
     */
    @Override
    public CheckInDetailVo getCheckInDetail(Long id) {
//        1.先new一个CheckInDetailVo对象然后往里填充
        CheckInDetailVo checkInDetailVo = new CheckInDetailVo();
//        2.先根据id查询一下入住信息
        CheckIn checkIn = checkInMapper.selectCheckInById(id);
//        2.先填充老人信息，然后填入checkInDetailVo中
        checkInDetailVo.setCheckInElderVo( getCheckInElderVo(checkIn));
//        3.填充家人信息，然后填入checkInDetailVo中
         checkInDetailVo.setElderFamilyVoList(getelderFamilyVoList(checkIn));
//        4.填充入住信息，然后填入checkInDetailVo中
        checkInDetailVo.setCheckInConfigVo(getCheckInConfigVo(checkIn));
//        5.填入合同表信息，然后填入checkInDetailVo中
        checkInDetailVo.setContract(getContract(checkIn));

        return checkInDetailVo;
    }

    /**
     * 查询合同表信息
     * @param checkIn
     * @return
     */
    private Contract getContract(CheckIn checkIn) {
//        根据老人id查找合同信息 返回
        Contract contract = contractMapper.selectOne(Wrappers.<Contract>lambdaQuery()
                .eq(Contract::getElderId,checkIn.getElderId()));
        return contract;
    }

    /**
     * 入住配置信息
     * @param checkIn
     * @return CheckInConfigVo
     */
    private CheckInConfigVo getCheckInConfigVo(CheckIn checkIn) {
//        根据checkIn的id查询入住配置信息表(check_in_config)
        CheckInConfig checkInConfig = checkInConfigMapper.selectOne(Wrappers.<CheckInConfig>lambdaQuery()
                .eq(CheckInConfig::getCheckInId,checkIn.getId()));
//        先把checkInConfig的信息填充到checkInConfigVo中
        CheckInConfigVo checkInConfigVo = BeanUtil.toBean(checkInConfig, CheckInConfigVo.class);
//        然后查看缺少的信息 填入
//        入住起始日期
        LocalDateTime startDate = checkIn.getStartDate();
        checkInConfigVo.setStartDate(checkIn.getStartDate());
//        入住结束日期
        LocalDateTime endDate = checkIn.getEndDate();
        checkInConfigVo.setEndDate(checkIn.getEndDate());
//        床号
        checkInConfigVo.setBedNumber(checkIn.getBedNumber());
        return checkInConfigVo;
    }

    /**
     * 填充家人信息
     * @param checkIn
     * @return
     */
    private List<ElderFamilyVo> getelderFamilyVoList(CheckIn checkIn) {
//        从备注中获取到家人信息，返回
        String Familys = checkIn.getRemark();
        List<ElderFamilyVo> list = JSONUtil.toList(Familys, ElderFamilyVo.class);
       return list;
    }

    /**
     * 填充入住老人信息
     * @param checkIn
     * @return CheckInElderVo
     */
    private CheckInElderVo getCheckInElderVo(CheckIn checkIn) {
//       目的：CheckIn提供的老人id查询老人表信息，然后填入CheckInElderVo中返回
//        1.CheckIn提供的老人id查询老人信息
        Elder elder = elderMapper.selectElderById(checkIn.getElderId());
//        2.看字段 发现 elder表的字段和 CheckInElderVo的字段大部分一样，所以先复制一下
        CheckInElderVo checkInElderVo = BeanUtil.toBean(elder, CheckInElderVo.class);
//        3.观察 字段属性 补全
//        年龄
        checkInElderVo.setAge(IDCardUtils.getAgeByIdCard(elder.getIdCardNo()));

        return checkInElderVo;
    }


}
